#!/usr/bin/python
# -*- coding: UTF-8 -*-    
# Author:Jruing
# FileName:WeWrokAPI
# DateTime:2021/7/21 15:26
# SoftWare: PyCharm
import traceback
from copy import copy
import requests
import os
from urllib3 import encode_multipart_formdata


class WeWorkAPI():
    """
    参考文档:https://work.weixin.qq.com/api/doc/90000/90136/91770#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E7%BE%A4%E6%9C%BA%E5%99%A8%E4%BA%BA
    """

    def __init__(self, key):
        self.key = key
        self.webhook = f"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={key}"
        self.header = {"Content-Type": "application/json"}

    def __str__(self):
        return f"webhook is {self.webhook}"

    def client_conn(self, data):
        try:
            response = requests.post(self.webhook, json=data, headers=self.header).json()
            return response
        except Exception:
            raise Exception(traceback.format_exc())

    # 发送文本类型信息
    def send_text_msg(self, content: str, mentioned_list: list = [],
                      mentioned_mobile_list: list = []) -> dict:
        """

        :param msgtype:消息类型，此时固定为text
        :param content:文本内容，最长不超过2048个字节，必须是utf8编码
        :param mentioned_list:userid的列表，提醒群中的指定成员(@某个成员)，@all表示提醒所有人，如果开发者获取不到userid，可以使用mentioned_mobile_list
        :param mentioned_mobile_list:手机号列表，提醒手机号对应的群成员(@某个成员)，@all表示提醒所有人
        :return:

        example:
        {
            "msgtype": "text",
            "text": {
                "content": "广州今日天气：29度，大部分多云，降雨概率：60%",
                "mentioned_list":["wangqing","@all"],
                "mentioned_mobile_list":["13800001111","@all"]
            }
        }
        """
        mentioned_lists = mentioned_list if isinstance(mentioned_list, list) and mentioned_list else []
        mentioned_mobile_lists = mentioned_mobile_list if isinstance(mentioned_list,
                                                                     list) and mentioned_mobile_list else []
        params = {
            "text": {
                "content": content,
                "mentioned_list": mentioned_lists,
                "mentioned_mobile_list": mentioned_mobile_lists
            },
            "msgtype": "text"
        }
        return self.client_conn(params)

    # 发送markdown类型消息
    def send_markdwon_msg(self, content: str) -> dict:
        """

        :param content:markdown内容，最长不超过4096个字节，必须是utf8编码
        :return:

        example:
        {
            "msgtype": "markdown",
            "markdown": {
                "content": "实时新增用户反馈<font color=\"warning\">132例</font>，请相关同事注意。\n
                 >类型:<font color=\"comment\">用户反馈</font>
                 >普通用户反馈:<font color=\"comment\">117例</font>
                 >VIP用户反馈:<font color=\"comment\">15例</font>"
            }
        }
        """
        params = {
            "msgtype": "markdown",
            "markdown": {
                "content": content,
            }
        }
        return self.client_conn(params)

    # 发送图片类型消息
    def send_image_msg(self, base64_value: str, md5_value: str) -> dict:
        """

        :param base64_value:图片内容的base64编码
        :param md5_value:图片内容（base64编码前）的md5值
        :return:
        注：图片（base64编码前）最大不能超过2M，支持JPG,PNG格式

        example:
        {
            "msgtype": "image",
            "image": {
                "base64": "DATA",
                "md5": "MD5"
            }
        }
        """
        params = {
            "msgtype": "image",
            "image": {
                "base64": base64_value,
                "md5": md5_value
            }
        }

        return self.client_conn(params)

    # 发送图文类型消息
    def send_link_msg(self, title: [], url: [], description: list = [], picurl: list = []) -> dict:
        """

        :param title:标题，不超过128个字节，超过会自动截断
        :param url:点击后跳转的链接。
        :param description:描述，不超过512个字节，超过会自动截断
        :param picurl:图文消息的图片链接，支持JPG、PNG格式，较好的效果为大图 1068*455，小图150*150。

        :return:

        example:
        {
            "msgtype": "news",
            "news": {
               "articles" : [
                   {
                       "title" : "中秋节礼品领取",
                       "description" : "今年中秋节公司有豪礼相送",
                       "url" : "www.qq.com",
                       "picurl" : "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png"
                   }
                ]
            }
        }
        """

        params = {
            "msgtype": "news",
            "news": {
                "articles": [

                ]
            }
        }
        if len(title) == len(url) and len(description) and len(picurl):
            for t, u, d, p in zip(title, url, description, picurl):
                article = {
                    "title": t,
                    "description": d,
                    "url": u,
                    "picurl": p
                }
                params['news']['articles'].append(article)

            return self.client_conn(params)
        else:
            raise Exception("检查title,url,description,picurl 的参数长度是否一致")

    # 发送文件类型
    def send_file_msg(self, media_id: str) -> dict:
        """

        :param media_id: 文件id，通过下文的文件上传接口获取
        :return:

        example:
        {
            "msgtype": "file",
            "file": {
                 "media_id": "3a8asd892asd8asd"
            }
        }
        """

        params = {
            "msgtype": "file",
            "file": {
                "media_id": media_id
            }
        }

        return self.client_conn(params)

    # 获取文件media_id
    def get_file_media_id(self, file_path, file_type: str):
        """

        :param file_path:  文件路径
        :param file_type:   媒体文件类型，分别有图片（image）、语音（voice）、视频（video），普通文件（file）
        :return:
        所有文件size必须大于5个字节
        图片（image）：2MB，支持JPG,PNG格式
        语音（voice） ：2MB，播放长度不超过60s，仅支持AMR格式
        视频（video） ：10MB，支持MP4格式
        普通文件（file）：20MB
        """
        if file_type in ['image', 'voice', 'video', 'file']:
            file_type = file_type
        else:
            raise Exception(
                "文件类型异常,请参考https://work.weixin.qq.com/api/doc/90000/90136/91770#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E7%BE%A4%E6%9C%BA%E5%99%A8%E4%BA%BA")
        file_upload_url = f"https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key={self.key}&type={file_type}"
        file_name = file_path.split("/")[-1]
        with open(file_path, 'rb') as f:
            length = os.path.getsize(file_path)
            data = f.read()
        headers = {"Content-Type": "application/octet-stream"}
        params = {
            "filename": file_name,
            "filelength": length,
        }
        file_data = copy(params)
        file_data['file'] = (file_path.split('/')[-1:][0], data)
        encode_data = encode_multipart_formdata(file_data)
        file_data = encode_data[0]
        headers['Content-Type'] = encode_data[1]
        response = requests.post(file_upload_url, data=file_data,
                                 headers={"Content-Type": "application/octet-stream"}).json()
        return response['media_id']

    def send_msg(self, send_type, **kwargs):
        try:
            _models = ["send_text_msg", "send_markdwon_msg", "send_image_msg", "send_link_msg",
                       "send_file_msg",
                       "get_file_media_id"]
            getattr(self, send_type)(**kwargs)
        except Exception:
            raise Exception(traceback.format_exc())

if __name__ == '__main__':
    vxbot = WeWorkAPI("xxxxxxxx")

